/*
 * registres.c
 *
 *  Created on: 2 janv. 2012
 *      Author: arthur
 */

#include "registres.h"

int toutSpiller(code4adresses * debut) {
	//contient l'element courant dont on veut spiller les variables
	code4adresses * instructionCourante = debut;
	while (instructionCourante != 0) {

		code4adresses * prochaineInstruction = instructionCourante->suivant;

		if ((instructionCourante->arg1 < r0 || instructionCourante->arg1 > ra)
				&& instructionCourante->typeArgs % 2 == 1) {
			if (arg1estEcrit(instructionCourante->instruction) == 1) {
				//L'argument 1 doit être chargé
				code4adresses * chargeArg1 = calloc(1, sizeof(code4adresses));
				chargeArg1->instruction = lw;
				chargeArg1->arg1 = a0;
				if (instructionCourante->arg1 < 0) {
					chargeArg1->arg2 = debutMemoireVariable - (4
							* instructionCourante->arg1);
				} else {
					chargeArg1 ->arg2 = instructionCourante->arg1;
				}
				chargeArg1->typeArgs = 1;
				instructionCourante->arg1 = a0;

				if (!estUnSaut(instructionCourante->instruction)) {
					chargeArg1->label = instructionCourante->label;
					instructionCourante->label = NULL;
				}

				chargeArg1->precedent = instructionCourante->precedent;
				if (chargeArg1->precedent != NULL) {
					chargeArg1->precedent->suivant = chargeArg1;
				}
				instructionCourante->precedent = chargeArg1;
				chargeArg1->suivant = instructionCourante;

			} else {
				//l'argument 1 doit être sauvegardé après l'instruction
				code4adresses * sauveArg1 = calloc(1, sizeof(code4adresses));
				sauveArg1->instruction = sw;
				sauveArg1->arg1 = v0;
				if (instructionCourante->arg1 < 0) {
					sauveArg1->arg2 = debutMemoireVariable - 4
							* instructionCourante->arg1;
				} else {
					sauveArg1->arg2 = instructionCourante->arg1;
				}
				sauveArg1->typeArgs = 1;
				instructionCourante->arg1 = v0;

				sauveArg1->suivant = instructionCourante->suivant;
				instructionCourante->suivant = sauveArg1;
				if (sauveArg1->suivant != NULL) {
					sauveArg1->suivant->precedent = sauveArg1;
				}
				sauveArg1->precedent = instructionCourante;
			}
		}
		if ((instructionCourante->arg2 < r0 || instructionCourante->arg2 > ra)
				&& (instructionCourante->typeArgs >> 1) % 2 == 1) {
			//l'argument 2 doit être chargé avant l'instruction
			code4adresses * chargeArg2 = calloc(1, sizeof(code4adresses));
			chargeArg2->instruction = lw;
			chargeArg2->arg1 = a1;
			if (instructionCourante->arg2 < 0) {
				chargeArg2->arg2 = debutMemoireVariable - 4
						* instructionCourante->arg2;
			} else {
				chargeArg2->arg2 = instructionCourante->arg2;
			}
			chargeArg2->typeArgs = 1;
			instructionCourante->arg2 = a1;

			chargeArg2->precedent = instructionCourante->precedent;
			if (chargeArg2->precedent != NULL) {
				chargeArg2->precedent->suivant = chargeArg2;
			}
			instructionCourante->precedent = chargeArg2;
			chargeArg2->suivant = instructionCourante;

			if (!estUnSaut(instructionCourante->instruction)) {
				chargeArg2->label = instructionCourante->label;
				instructionCourante->label = NULL;
			}
		}
		if ((instructionCourante->arg3 < r0 || instructionCourante->arg3 > ra)
				&& (instructionCourante->typeArgs >> 2) % 2 == 1) {
			//l'argument 2 doit être chargé avant l'instruction
			code4adresses * chargeArg3 = calloc(1, sizeof(code4adresses));
			chargeArg3->instruction = lw;
			chargeArg3->arg1 = a2;
			if (instructionCourante->arg3 < 0) {
				chargeArg3->arg2 = debutMemoireVariable - 4
						* instructionCourante->arg3;
			} else {
				chargeArg3->arg2 = instructionCourante->arg3;
			}
			chargeArg3->typeArgs = 1;
			instructionCourante->arg3 = a2;

			chargeArg3->precedent = instructionCourante->precedent;
			if (chargeArg3->precedent != NULL) {
				chargeArg3->precedent->suivant = chargeArg3;
			}
			instructionCourante->precedent = chargeArg3;
			chargeArg3->suivant = instructionCourante;

			if (!estUnSaut(instructionCourante->instruction)) {
				chargeArg3->label = instructionCourante->label;
				instructionCourante->label = NULL;
			}
		}

		instructionCourante = prochaineInstruction;

	}
	return 0;
}

void allouerMemoireTableau(variable * tableau) {
	int taille = 4;
	int i;
	for (i = 0; i < tableau->dimenssions; i++) {
		taille *= (tableau->bornesSup[i] - tableau->bornesInf[i]+1);
	}
	tableau->numeroVariableTemporaire = sommetTableau;
	sommetTableau += taille;
}

int calculerAdresseCaseTableauStatic(variable * tableau, int dimenssion,
		int * indexes) {
	int taille = 0;
	int offset = 4;
	if (dimenssion > tableau->dimenssions) {
		taille = -1;
	} else {
		int i;
		for (i = 0; i < tableau->dimenssions; i++) {
			if (i <= dimenssion) {
				taille += offset * (indexes[i] - tableau->bornesInf[i]);
			}
			offset *= (tableau->bornesSup[i] - tableau->bornesInf[i]+1);
		}
	}
	return taille;
}
